package com.siwei.mes.controller.common;

import com.alibaba.fastjson.JSONArray;
import com.siwei.mes.common.annotation.AnonymousAccess;
import com.siwei.mes.common.base.BaseParams;
import com.siwei.mes.common.result.ApiResult;
import com.siwei.mes.common.result.Json;
import com.siwei.mes.common.util.MacTools;
import com.siwei.mes.entity.dto.UploadDto;
import com.siwei.mes.entity.vo.UploadVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.siwei.mes.common.exception.handler.MessageHandler.assertTrue;

/**
 * @Description: 上传文件Controller
 * @Version: 1.0
 * @author: chenmaolin
 * @date: 2021-11-09
 */
@Slf4j
@RestController
@RequestMapping("/upload")
@Api(value = "上传文件", tags = "上传文件接口")
public class UploadController {

    @Value(value = "${file.mac}")
    private String ADDRESS_MAC;
    @Value(value = "${file.windows}")
    private String ADDRESS_WINDOWS;
    @Value(value = "${file.linux}")
    private String ADDRESS_LINUX;


    @Value(value = "${excel.mac}")
    private String EXCLE_ADDRESS_MAC;
    @Value(value = "${excel.windows}")
    private String EXCLE_ADDRESS_WINDOWS;
    @Value(value = "${excel.linux}")
    private String EXCLE_ADDRESS_LINUX;

    @Value(value = "${server.port}")
    private String port;

    /**
     * 根据服务类型获取磁盘路径
     * 默认是windows磁盘路径
     *
     * @return
     */
    public String getPathName() {
        String operSystem = MacTools.getOperSystem();
        if (Arrays.stream(BaseParams.MAC_LIST).parallel().anyMatch(operSystem::contains)) {
            return ADDRESS_MAC;
        } else if (Arrays.stream(BaseParams.LINUX_LIST).parallel().anyMatch(operSystem::contains)) {
            return ADDRESS_LINUX;
        }
        return ADDRESS_WINDOWS;
    }


    /**
     * 根据服务类型获取磁盘路径
     * 默认是windows磁盘路径
     *
     * @return
     */
    public String getExcelPathName() {
        String operSystem = MacTools.getOperSystem();
        if (Arrays.stream(BaseParams.MAC_LIST).parallel().anyMatch(operSystem::contains)) {
            return EXCLE_ADDRESS_MAC;
        } else if (Arrays.stream(BaseParams.LINUX_LIST).parallel().anyMatch(operSystem::contains)) {
            return EXCLE_ADDRESS_LINUX;
        }
        return EXCLE_ADDRESS_WINDOWS;
    }

    @ApiOperation("获取可访问图片地址")
    @PostMapping("getFileView")
    public Json getFileView(@RequestBody @Validated UploadVo uploadVo, HttpServletRequest request) {
        assertTrue(StringUtils.isBlank(uploadVo.getFileName()), "图片名称为空");
        Integer type = uploadVo.getType();
        if (type == 1) {
            UploadDto uploadDto = new UploadDto().setType(type).setFileName(uploadVo.getFileName())
                    .setFilePath(replacePath(uploadVo.getFileName(), request));
            return Json.succ().data(uploadDto);
        }
        return Json.succ().data(new ApiResult());
    }

    @ApiOperation("获取可访问图片地址-多个")
    @PostMapping("getFileViewList")
    public Json getFileViewList(@RequestBody @Validated UploadVo uploadVo, HttpServletRequest request) {
        List<UploadDto> list = new ArrayList<>();
        assertTrue(uploadVo.getFileList().isEmpty(), "图片名称集合为空");
        Integer type = uploadVo.getType();
        if (type == 1) {
            for (String fileName : uploadVo.getFileList()) {
                UploadDto uploadDto = new UploadDto().setType(type).setFileName(fileName)
                        .setFilePath(replacePath(fileName, request));
                list.add(uploadDto);
            }
        }
        return Json.succ().data(ApiResult.addList(list));
    }

    @AnonymousAccess
    @ApiOperation(value = "图片前缀")
    @GetMapping("getPrefixPath")
    public Json getPrefixPath(HttpServletRequest request) {
        /**获取服务器路径*/
        String requestUrl = getServerUrl(request);
        String prefix = requestUrl + "/image/";
        return Json.succ().data(ApiResult.addColumn("filePrefix", prefix));
    }


    /**
     * 文件上传
     *
     * @param file    单个
     * @param request
     * @return excelPath 图片地址
     */
    @ApiOperation(value = "excel文件上传")
    @PostMapping("/excelFile")
    public Json uploadExcelFile(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
        String pathName = getExcelPathName();
        if (file.isEmpty()) {
            throw new RuntimeException("excel上传文件不能为空");
        }
        Map<String, String> map = this.commonExcelUpload(file, pathName, request);
        return Json.succ().data(map);
    }


    /**
     * 文件上传
     *
     * @param file    单个
     * @param request
     * @return imagePath 图片地址
     */
    @ApiOperation(value = "文件上传（多个）")
    @PostMapping("/file")
    public Json uploadFile(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
        String pathName = getPathName();
        if (file.isEmpty()) {
            throw new RuntimeException("上传文件不能为空");
        }
        Map<String, String> map = this.commonUpload(file, pathName, request);
        return Json.succ().data(map);
    }

    /**
     * 文件上传（批量）
     *
     * @param fileList
     * @param request
     * @return imagePath 图片地址
     */
    @ApiOperation(value = "文件上传（多个）")
    @PostMapping("/fileList")
    public Json uploadFile(@RequestParam("fileList") List<MultipartFile> fileList, HttpServletRequest request) {
        List<Map<String, String>> mapList = new ArrayList<>();
        String pathName = getPathName();
        if (fileList.isEmpty()) {
            throw new RuntimeException("上传文件不能为空");
        }
        for (MultipartFile file : fileList) {
            Map<String, String> map = this.commonUpload(file, pathName, request);
            mapList.add(map);
        }
        return Json.succ().data(ApiResult.addList(mapList));
    }

    /**
     * 上传方法
     *
     * @param file     文件
     * @param pathName 文件地址
     * @param request  request
     * @return
     */
    public Map<String, String> commonUpload(MultipartFile file, String pathName, HttpServletRequest request) {
        if (file == null || StringUtils.isBlank(file.getOriginalFilename())) {
            throw new RuntimeException("上传文件为空");
        }
        /**读取文件内容并写入 指定目录中*/
        String fileName = null;
        try {
            fileName = URLEncoder.encode(file.getOriginalFilename(), "UTF-8");
            /**这里把百分号替换为空*/
            fileName = fileName.replaceAll("%", "");
            // fileName = replaceChinese(fileName, "");
            // fileName = getPrefix() + fileName;

            File dest = new File(pathName + fileName);
            /**判断目录是否存在*/
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }
            file.transferTo(dest);
        } catch (Exception e) {
            throw new RuntimeException("后台也不知道为什么, 反正就是上传失败了");
        }
        String imagePath = replacePath(fileName, request);
        Map<String, String> map = new HashMap<>(2);
        map.put("fileName", fileName);
        map.put("filePath", imagePath);
        log.info("上传文件成功,路径：【{}】,图片名称：【{}】", pathName, fileName);
        return map;
    }


    public Map<String, String> commonExcelUpload(MultipartFile file, String pathName, HttpServletRequest request) {
        if (file == null || StringUtils.isBlank(file.getOriginalFilename())) {
            throw new RuntimeException("上传文件为空");
        }
        /**读取文件内容并写入 指定目录中*/
        String fileName = null;
        try {
            fileName = URLEncoder.encode(file.getOriginalFilename(), "UTF-8");
            /**这里把百分号替换为空*/
            fileName = fileName.replaceAll("%", "");


            File dest = new File(pathName + fileName);
            /**判断目录是否存在*/
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }
            file.transferTo(dest);
        } catch (Exception e) {
            throw new RuntimeException("上传失败");
        }
        String excelPath = replacePathExcel(fileName, request, port);
        Map<String, String> map = new HashMap<>(2);
        map.put("fileName", fileName);
        map.put("filePath", excelPath);
        log.info("上传文件成功,路径：【{}】,excel名称：【{}】", pathName, fileName);
        return map;
    }

    /**
     * 增加服务器路径
     *
     * @param excel
     * @param request
     * @return
     */
    public static String replacePathExcel(String excel, HttpServletRequest request, String port) {
        String result = "";
        if (org.apache.commons.lang.StringUtils.isNotEmpty(excel)) {
            /**获取服务器路径*/
            /**当前链接使用的协议*/
            String requestUrl = request.getScheme() + "://" + request.getServerName()// 服务器地址
                    + ":" + port // 端口号
                    + request.getContextPath();

            if (!"".equals(excel)) {
                result = requestUrl + "/excel/" + excel;
            }
        }
        return result;
    }


    /**
     * 生成图片前缀
     *
     * @return
     */
    public static String getPrefix() {
        Base64.Encoder encoder = Base64.getEncoder();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String str = sdf.format(new Date());
        byte[] bytes = str.getBytes();
        // base64
        str = encoder.encodeToString(bytes);
        return str;
    }


    /***
     * 把中文,把','或'，'替换为指定字符,<br>
     * 注意:一次只匹配一个中文字符
     * @param source
     * @param replacement
     * @return
     */
    public static String replaceChinese(String source, String replacement) {
        String reg = "[\u4e00-\u9fa5]";
        Pattern pat = Pattern.compile(reg);
        Matcher mat = pat.matcher(source);
        return mat.replaceAll(replacement).replaceAll(",", replacement).replaceAll("，", replacement);
    }

    /**
     * 增加服务器路径
     *
     * @param photo
     * @param request
     * @return
     */
    public String replacePath(String photo, HttpServletRequest request) {
        String result = "";
        if (StringUtils.isNotEmpty(photo)) {
            /**获取服务器路径*/
            String requestUrl = getServerUrl(request);
            if (!photo.isEmpty()) {
                result = requestUrl + "/image/" + photo;
            }
        }
        return result;
    }


    /**
     * 删除服务器路径
     *
     * @param photo
     * @return
     */
    public static String deletePath(String photo) {
        String result = "";
        if (StringUtils.isNotEmpty(photo)) {
            result = photo.substring(photo.lastIndexOf("/") + 1);
        }
        return result;
    }

    /**
     * 删除服务器路径  JSONArray
     *
     * @param jsonArray
     * @return
     */
    public static JSONArray deletePath(JSONArray jsonArray) {
        JSONArray result = new JSONArray();
        if (jsonArray == null) {
            return result;
        }
        for (Object o : jsonArray) {
            String photo = String.valueOf(o);
            if (StringUtils.isNotEmpty(photo)) {
                result.add(photo.substring(photo.lastIndexOf("/") + 1));
            }
        }
        return result;
    }

    /**
     * 获取服务器url路径
     *
     * @param request
     * @return
     */
    public String getServerUrl(HttpServletRequest request) {
        /**当前链接使用的协议*/
        return request.getScheme() + "://" + request.getServerName()// 服务器地址
                + ":" + port // 端口号
                + request.getContextPath();
    }

    /**
     * base64 转文件
     *
     * @param base64   base64
     * @param fileName 文件名称
     * @param savePath 路径
     */
    public static void base64ToFile(String base64, String fileName, String savePath) {
        File file = null;
        // 创建文件目录
        File dir = new File(savePath);
        if (!dir.exists() && !dir.isDirectory()) {
            dir.mkdirs();
        }
        BufferedOutputStream bos = null;
        java.io.FileOutputStream fos = null;
        try {
            if (base64.contains("data:")) {
                int start = base64.indexOf(",");
                base64 = base64.substring(start + 1);
            } else {
                return;
            }
            final Base64.Decoder decoder = Base64.getDecoder();
            base64 = base64.replaceAll("\r|\n", "");
            base64 = base64.trim();
            byte[] bytes = decoder.decode(base64);

//            byte[] bytes = Base64.getDecoder().decode(base64);
            file = new File(savePath + fileName);
            fos = new java.io.FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 中文转二进制
     *
     * @param chinese
     * @return
     */
    public static String chineseToBinary(String chinese) {
        byte[] bytes = chinese.getBytes();
        StringBuilder binaryStr = new StringBuilder();
        for (byte b : bytes) {
            binaryStr.append(Integer.toBinaryString(b));
        }
        return binaryStr.toString();
    }


    public static void main(String[] args) {
        String str = "http://localhost:8990/image/MjAyMjA5MTgyMDQxNTU=aldajslkajslajs.jpg";
        String s = deletePath(str);
        System.out.println(s);
//        String str = "http://demo.mytongche.com:80/tongxue-fujian/image/http://demo.mytongche.com:80/tongxue-fujian/image/MjAyMTExMTUwOTAyNTk=_20211108104125.png";
//        String str1 = "MjAyMTExMTUwOTAyNTk=_20211108104125.png";
//        System.out.println(str1.substring(str1.lastIndexOf("/") + 1));
//
//        System.out.println(getPrefix());
    }
}
